package cs275.ants.graphics;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;

import com.jme.bounding.BoundingSphere;
import com.jme.image.Texture;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.TriMesh;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jme.util.export.Savable;
import com.jme.util.export.binary.BinaryExporter;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.effects.particles.ParticleFactory;
import com.jmex.effects.particles.ParticleMesh;
import com.jmex.model.converters.FormatConverter;
import com.jmex.model.converters.ObjToJme;

public class Resources {

	private TriMesh antMesh;
	ByteArrayOutputStream antMeshBin = new ByteArrayOutputStream();

	private ParticleMesh pMesh;
	ByteArrayOutputStream pMeshBin = new ByteArrayOutputStream();

	public TriMesh antMesh() throws IOException {
		if (antMesh == null) {
			URL modelLocation = CharacterGenerator.class.getClassLoader()
					.getResource("resources/model/ant/formicarufa.obj");
			// Create something to convert .obj format to .jme
			FormatConverter converter = new ObjToJme();
			// Point the converter to where it will find the .mtl file from
			converter.setProperty("mtllib", modelLocation);
			converter.setProperty("texdir", modelLocation);
			// This byte array will hold my .jme file
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
			// Use the format converter to convert .obj to .jme
			converter.convert(modelLocation.openStream(), outputStream);
			antMesh = (TriMesh) BinaryImporter.getInstance().load(
					new ByteArrayInputStream(outputStream.toByteArray()));
			try {
				BinaryExporter.getInstance().save(antMesh, antMeshBin);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			return antMesh;
		}else 
			return cloneTriMesh();
	}

	public ParticleMesh particleMesh() {
		if (pMesh == null) {
			DisplaySystem ds = DisplaySystem.getDisplaySystem();
			BlendState as1 = ds.getRenderer().createBlendState();
			as1.setBlendEnabled(true);
			as1.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
			as1.setDestinationFunction(BlendState.DestinationFunction.One);
			as1.setTestEnabled(true);
			as1.setTestFunction(BlendState.TestFunction.GreaterThan);
			as1.setEnabled(true);

			TextureState ts = ds.getRenderer().createTextureState();
			ts.setTexture(TextureManager.loadTexture(ParticleGenerator.class
					.getClassLoader().getResource(
							"resources/textures/flaresmall.jpg"),
					Texture.MinificationFilter.Trilinear,
					Texture.MagnificationFilter.Bilinear));
			ts.setEnabled(true);
			pMesh = ParticleFactory.buildParticles("particles", 300);
			pMesh.setEmissionDirection(new Vector3f(1, 0, 1));
			pMesh.setInitialVelocity(.006f);
			pMesh.setStartSize(2.5f);
			pMesh.setEndSize(.5f);
			pMesh.setMinimumLifeTime(1200f);
			pMesh.setMaximumLifeTime(1400f);
			pMesh.setReleaseRate(10);
			pMesh.setLocalScale(4);
			pMesh.setStartColor(new ColorRGBA(1, 1, 0, 0.3f));
			pMesh.setEndColor(new ColorRGBA(1, 0, 0, 0));
			pMesh.setMaximumAngle(360f * FastMath.DEG_TO_RAD);
			pMesh.setParticlesInWorldCoords(true);
			pMesh.warmUp(60);

			pMesh.setRenderState(ts);
			pMesh.setRenderState(as1);
			ZBufferState zstate = ds.getRenderer().createZBufferState();
			zstate.setEnabled(false);
			pMesh.setRenderState(zstate);
			pMesh.setModelBound(new BoundingSphere());
			pMesh.updateModelBound();
			pMesh.getParticleController().setControlFlow(true);
			try {
				BinaryExporter.getInstance().save(pMesh, pMeshBin);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return pMesh;
		}
		else return cloneParticleMesh();
	}

	private TriMesh cloneTriMesh() {
		ByteArrayInputStream in = new ByteArrayInputStream(antMeshBin
				.toByteArray());
		try {
			TriMesh ant = (TriMesh) BinaryImporter.getInstance()
					.load(in);
			antMeshBin.close();
			in.close();
			return ant;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	private ParticleMesh cloneParticleMesh() {
		ByteArrayInputStream in = new ByteArrayInputStream(pMeshBin
				.toByteArray());
		try {
			ParticleMesh particle = (ParticleMesh) BinaryImporter.getInstance()
					.load(in);
			pMeshBin.close();
			in.close();
			return particle;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
}
